
#include "MyDrawingArea.h"
using namespace std;

void MyDrawingArea::drawSelrect()
{
    cr = get_window()->create_cairo_context();
    if (Debug::test(DEBUG_DRAW)) {
        cout << "drawing selrect" << endl;
    }
    cr->set_line_width(m_srect.m_sideThickness = 1);
    cr->set_source_rgb(0.8, 0.0, 0.0);

    cr->move_to(m_srect.m_x1, m_srect.m_y1);
    cr->line_to(m_srect.m_x1, m_srect.m_y2);
    cr->line_to(m_srect.m_x2, m_srect.m_y2);
    cr->line_to(m_srect.m_x2, m_srect.m_y1);
    cr->line_to(m_srect.m_x1, m_srect.m_y1);
    cr->stroke();



    cr->move_to(m_srect.m_x1 + SEL_REC_ARC_RAD, m_srect.m_y1);
    cr->arc(m_srect.m_x1, m_srect.m_y1, SEL_REC_ARC_RAD, 0, M_PI/2.0);
    cr->stroke();

    cr->move_to(m_srect.m_x1, m_srect.m_y2 - SEL_REC_ARC_RAD);
    cr->arc(m_srect.m_x1, m_srect.m_y2, SEL_REC_ARC_RAD, 3/2.0 * M_PI, 0 * M_PI);
    cr->stroke();

    cr->move_to(m_srect.m_x2 - SEL_REC_ARC_RAD, m_srect.m_y2);
    cr->arc(m_srect.m_x2, m_srect.m_y2, SEL_REC_ARC_RAD, M_PI, 3/2.0 * M_PI);
    cr->stroke();

    cr->move_to(m_srect.m_x2, m_srect.m_y1 + SEL_REC_ARC_RAD);
    cr->arc(m_srect.m_x2, m_srect.m_y1, SEL_REC_ARC_RAD, M_PI/2.0, M_PI);
    cr->stroke();
}


MyDrawingArea::MyDrawingArea()
{
    add_events( Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK |
        Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK );
    memset(&m_srect, 0, sizeof(m_srect));
    m_srect.m_sideThickness = 1;
    m_srect.m_x1 = SEL_REC_INIT_X;
    m_srect.m_y1 = SEL_REC_INIT_Y;
    m_srect.m_x2 = SEL_REC_INIT_X + MIN_SEL_REC_LENGTH;
    m_srect.m_y2 = SEL_REC_INIT_Y + MIN_SEL_REC_LENGTH;
}

MyDrawingArea::~MyDrawingArea()
{
}

void MyDrawingArea::selrectTrack(GdkEventButton* event)
{

}


bool MyDrawingArea::on_button_press_event(GdkEventButton* event)
{

    if ( !( (event->type == GDK_BUTTON_PRESS) && (event->button == 1) ) ) {
        return 0;
    }

    if (Debug::test(DEBUG_INFO)) {
        cout << "-----------------------------" << endl;
        cout << "drawing area mouse down called" << endl;
    }
//    if(!m_srect.m_visible) {
//        return 1;
//    }
    if (Debug::test(DEBUG_EVENT)) {
        cout << "drawing area mouse down inside the sel rectat " << event-> x << " " << event->y << endl;
        cout << m_srect.m_x1 << " " << m_srect.m_x2 << " " << m_srect.m_y1 << " " << m_srect.m_y2 << endl;
    }
    if(event->x < m_srect.m_x1 || event->x > m_srect.m_x2 || event->y < m_srect.m_y1 || event->y > m_srect.m_y2) {
        return 0;
    }

    if (Debug::test(DEBUG_EVENT)) {
        cout << "drawing area mouse down inside the sel rectat " << event-> x << " " << event->y << endl;
        cout << m_srect.m_x1 << " " << m_srect.m_x2 << " " << m_srect.m_y1 << " " << m_srect.m_y2 << endl;
    }

    m_srect.m_mouseDown = true;

    m_srect.m_mouseLastX = event->x;
    m_srect.m_mouseLastY = event->y;

    if(event->x - m_srect.m_x1 <= SEL_REC_ARC_RAD) {

        if(event->y -m_srect.m_y1 <= SEL_REC_ARC_RAD) {
            m_srect.capturedSide = TOP_LEFT;
        } else if(m_srect.m_y2 - event->y <= SEL_REC_ARC_RAD) {
            m_srect.capturedSide = BOTTOM_LEFT;
        } else {
            m_srect.capturedSide = LEFT;
        }
        if (Debug::test(DEBUG_INFO)) {
            cout << "left" << endl;
        }

    } else if(m_srect.m_x2 - event->x <= SEL_REC_ARC_RAD) {


        if(event->y -m_srect.m_y1 <= SEL_REC_ARC_RAD) {
            m_srect.capturedSide = TOP_RIGHT;
        } else if(m_srect.m_y2 - event->y <= SEL_REC_ARC_RAD) {
            m_srect.capturedSide = BOTTOM_RIGHT;
        } else {
            m_srect.capturedSide = RIGHT;
        }
        if (Debug::test(DEBUG_INFO)) {
            cout << "right";
        }

    } else if(event->y - m_srect.m_y1 <= SEL_REC_ARC_RAD) {
        m_srect.capturedSide = TOP;
        if (Debug::test(DEBUG_INFO)) {
            cout << "top" << endl;
        }

    } else if( m_srect.m_y2 - event->y <= SEL_REC_ARC_RAD) {
        m_srect.capturedSide = BOTTOM;
        if (Debug::test(DEBUG_INFO)) {
            cout << "down" << endl;
        }

    } else {
        m_srect.capturedSide = CENTER;
    }

    if (Debug::test(DEBUG_INFO)) {
        cout << "pressed the mouse button --->" <<  m_srect.capturedSide << endl;
    }
    return 1;
}

bool MyDrawingArea::on_button_release_event(GdkEventButton* event)
{
    if (Debug::test(DEBUG_INFO)) {
        cout << "Released at " << event->x << " " << event->y << endl;
    }
       if ( !( (event->type == GDK_BUTTON_RELEASE) && (event->button == 1) ) ) {
        return 1;
    }

    if(event->x < 0 || event->x > 300 || event->y < 0 || event->y > 300) {
        return 1;
    }

    if (!m_srect.m_mouseDown) {
        return 1;
    }
    if (Debug::test(DEBUG_INFO)) {
        cout << "going to reposition sel rect ";
    }
    switch (m_srect.capturedSide) {
        case LEFT:
        {
            m_srect.m_x1 = event->x;
            if(m_srect.m_x2 - m_srect.m_x1 < 10) {
                m_srect.m_x1 = m_srect.m_x2 - 10;
            }
            if (Debug::test(DEBUG_INFO)) {
                cout << "to left" << endl;
            }
            break;
        }

        case RIGHT:
        {
            m_srect.m_x2 = event->x;
            if(m_srect.m_x2 - m_srect.m_x1 < 10) {
                m_srect.m_x2 = m_srect.m_x1 + 10;
            }
            if (Debug::test(DEBUG_INFO)) {
                cout << "to right" << endl;
            }
            break;
        }

        case TOP:
        {
            m_srect.m_y1 = event->y;
            if(m_srect.m_y2 - m_srect.m_y1 < 10) {
                m_srect.m_y1 = m_srect.m_y2 - 10;
            }
            if (Debug::test(DEBUG_INFO)) {
                cout << "to top" << endl;
            }
            break;
        }

        case BOTTOM:
        {
            m_srect.m_y2 = event->y;
            if(m_srect.m_y2 - m_srect.m_y1 < 10) {
                m_srect.m_y2 = m_srect.m_y1 + 10;
            }
            if (Debug::test(DEBUG_INFO)) {
                cout << "to bottom" << endl;
            }
            break;
        }

        case TOP_LEFT:
        {
            m_srect.m_x1 = event->x;
            m_srect.m_y1 = event->y;
            if(m_srect.m_x2 - m_srect.m_x1 < 10) {
                m_srect.m_x1 = m_srect.m_x2 - 10;
            }
            if(m_srect.m_y2 - m_srect.m_y1 < 10) {
                m_srect.m_y1 = m_srect.m_y2 - 10;
            }
            if (Debug::test(DEBUG_INFO)) {
                cout << "to top left" << endl;
            }
            break;
        }

        case TOP_RIGHT:
        {
            m_srect.m_x2 = event->x;
            m_srect.m_y1 = event->y;
            if(m_srect.m_x2 - m_srect.m_x1 < 10) {
               m_srect.m_x2 = m_srect.m_x1 + 10;
            }
            if(m_srect.m_y2 - m_srect.m_y1 < 10) {
                m_srect.m_y1 = m_srect.m_y2 - 10;
            }
            if (Debug::test(DEBUG_INFO)) {
                cout << "to top right" << endl;
            }
            break;
        }

        case BOTTOM_LEFT:
        {
            m_srect.m_x1 = event->x;
            m_srect.m_y2 = event->y;
            if(m_srect.m_y2 - m_srect.m_y1 < 10) {
               m_srect.m_y2 = m_srect.m_y1 + 10;
            }
            if(m_srect.m_x2 - m_srect.m_x1 < 10) {
            m_srect.m_x1 = m_srect.m_x2 - 10;
            }
            if (Debug::test(DEBUG_INFO)) {
                cout << "to bottom left" << endl;
            }
            break;
        }

        case BOTTOM_RIGHT:
        {
            m_srect.m_x2 = event->x;
            m_srect.m_y2 = event->y;
            if(m_srect.m_y2 - m_srect.m_y1 < 10) {
               m_srect.m_y2 = m_srect.m_y1 + 10;
            }
            if(m_srect.m_x2 - m_srect.m_x1 < 10) {
                m_srect.m_x2 = m_srect.m_x1 + 10;
            }
            if (Debug::test(DEBUG_INFO)) {
                cout << "to bottom right" << endl;
            }
            break;
        }

        case CENTER:
        {
            int xdisp = event->x - m_srect.m_mouseLastX;
            int ydisp = event->y - m_srect.m_mouseLastY;
            m_srect.m_x2 += xdisp;
            m_srect.m_y2 += ydisp;
            m_srect.m_x1 += xdisp;
            m_srect.m_y1 += ydisp;
            if (Debug::test(DEBUG_INFO)) {
                cout << "new pos" << endl;
            }
            break;
        }
    }

    repaint();
    m_srect.m_mouseDown = false;
    return 1;
}

bool MyDrawingArea::on_motion_notify_event (GdkEventMotion* event)
{
    if (!m_srect.m_mouseDown) {
        return 1;
    }
    if (Debug::test(DEBUG_INFO)) {
        cout << "Current pos at " << event->x << " " << event->y << endl;
        cout << "going to reposition sel rect ";
    }

    if(event->x < 0 || event->x > 300 || event->y < 0 || event->y > 300) {
        return 1;
    }

    switch (m_srect.capturedSide) {
        case LEFT:
        {
            m_srect.m_x1 = event->x;
            if(m_srect.m_x2 - m_srect.m_x1 < 10) {
                m_srect.m_x1 = m_srect.m_x2 - 10;
            }
            if (Debug::test(DEBUG_INFO)) {
                cout << "to left" << endl;
            }
            break;
        }

        case RIGHT:
        {
            m_srect.m_x2 = event->x;
            if(m_srect.m_x2 - m_srect.m_x1 < 10) {
                m_srect.m_x2 = m_srect.m_x1 + 10;
            }
            if (Debug::test(DEBUG_INFO)) {
                cout << "to right" << endl;
            }
            break;
        }

        case TOP:
        {
            m_srect.m_y1 = event->y;
            if(m_srect.m_y2 - m_srect.m_y1 < 10) {
                m_srect.m_y1 = m_srect.m_y2 - 10;
            }
            if (Debug::test(DEBUG_INFO)) {
                cout << "to top" << endl;
            }
            break;
        }

        case BOTTOM:
        {
            m_srect.m_y2 = event->y;
            if(m_srect.m_y2 - m_srect.m_y1 < 10) {
                m_srect.m_y2 = m_srect.m_y1 + 10;
            }
            if (Debug::test(DEBUG_INFO)) {
                cout << "to bottom" << endl;
            }
            break;
        }

        case TOP_LEFT:
        {
            m_srect.m_x1 = event->x;
            m_srect.m_y1 = event->y;
            if(m_srect.m_x2 - m_srect.m_x1 < 10) {
                m_srect.m_x1 = m_srect.m_x2 - 10;
            }
            if(m_srect.m_y2 - m_srect.m_y1 < 10) {
                m_srect.m_y1 = m_srect.m_y2 - 10;
            }
            if (Debug::test(DEBUG_INFO)) {
                cout << "to top left" << endl;
            }
            break;
        }

        case TOP_RIGHT:
        {
            m_srect.m_x2 = event->x;
            m_srect.m_y1 = event->y;
            if(m_srect.m_x2 - m_srect.m_x1 < 10) {
               m_srect.m_x2 = m_srect.m_x1 + 10;
            }
            if(m_srect.m_y2 - m_srect.m_y1 < 10) {
                m_srect.m_y1 = m_srect.m_y2 - 10;
            }
            if (Debug::test(DEBUG_INFO)) {
                cout << "to top right" << endl;
            }
            break;
        }

        case BOTTOM_LEFT:
        {
            m_srect.m_x1 = event->x;
            m_srect.m_y2 = event->y;
            if(m_srect.m_y2 - m_srect.m_y1 < 10) {
               m_srect.m_y2 = m_srect.m_y1 + 10;
            }
            if(m_srect.m_x2 - m_srect.m_x1 < 10) {
            m_srect.m_x1 = m_srect.m_x2 - 10;
            }
            if (Debug::test(DEBUG_INFO)) {
                cout << "to bottom left" << endl;
            }
            break;
        }

        case BOTTOM_RIGHT:
        {
            m_srect.m_x2 = event->x;
            m_srect.m_y2 = event->y;
            if(m_srect.m_y2 - m_srect.m_y1 < 10) {
               m_srect.m_y2 = m_srect.m_y1 + 10;
            }
            if(m_srect.m_x2 - m_srect.m_x1 < 10) {
                m_srect.m_x2 = m_srect.m_x1 + 10;
            }
            if (Debug::test(DEBUG_INFO)) {
                cout << "to bottom right" << endl;
            }
            break;
        }

        case CENTER:
        {
            int xdisp = event->x - m_srect.m_mouseLastX;
            int ydisp = event->y - m_srect.m_mouseLastY;
            m_srect.m_x2 += xdisp;
            m_srect.m_y2 += ydisp;
            m_srect.m_x1 += xdisp;
            m_srect.m_y1 += ydisp;
            m_srect.m_mouseLastX = event->x;
            m_srect.m_mouseLastY = event->y;
            if (Debug::test(DEBUG_INFO)) {
                cout << "new pos" << endl;
            }
            break;
        }
    }

    repaint();
    return 1;
}


bool MyDrawingArea::on_expose_event(GdkEventExpose* ev)
{
    if (Debug::test(DEBUG_EVENT)) {
        cout << "MyDrawingArea on_expose_event" << endl;
    }
    repaint();
    return 0;
}

bool MyDrawingArea::repaint(void)
{
    if (m_image) {
        m_image->render_to_drawable(get_window(), get_style()->get_black_gc(),
            m_src_x, m_src_y, 0, 0, m_width, m_height, Gdk::RGB_DITHER_NONE, 0, 0);
//        if(m_srect.m_visible) {
            drawSelrect();
//        }
    }
    return false;
}


void MyDrawingArea::setImage(Glib::RefPtr<Gdk::Pixbuf> &image, int src_x, int src_y, int width, int height)
{
    m_image = image;
    m_src_x = src_x;
    m_src_y = src_y;
    m_width = width;
    m_height = height;
}
